using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using GotLyrics;
using System.IO;
using System.Net;

namespace GotLyrics_Console
{
    class Program
    {
        private static bool _skip;
        private static bool _force;
        private static bool _display;
        private static bool _test;
        private static bool _saveLyricsToTextFile;

        private static UltraGrabber _ultraGrabber = new UltraGrabber();

        private static int _skippedCount;
        private static int _taggedCount;
        private static List<string> _noLyricsFilenames = new List<string>();

        static void Main(string[] args)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            string asmName = asm.GetName().Name;
            string version = Common.GetAssemblyFileVersion(asm);
            Console.WriteLine("{0} v{1}", asmName, version);

            if (ParseArguments(args))
            {
                RegisterEvents();

                try
                {
                    _ultraGrabber.Execute();

                    Console.WriteLine("-------------------------------------------------------------------------------");
                    if (_noLyricsFilenames.Count > 0)
                    {
                        Console.WriteLine("Could not find lyrics for the following files:");
                        foreach (string file in _noLyricsFilenames)
                        {
                            Console.WriteLine(file);
                        }
                    }
                    Console.WriteLine("Files tagged: " + _taggedCount.ToString());
                    Console.WriteLine("Files skipped: " + _skippedCount.ToString());
                    
                    Console.WriteLine("Done.");


                }
                catch (ValidationException ex)
                {
                    Console.WriteLine(ex.Message);
                    DisplayUsage();
                }
            }
        }

        private static void RegisterEvents()
        {
            _ultraGrabber.ScanDirectory += new EventHandler<ScanDirectoryEventArgs>(UltraGrabber_ScanDirectory);
            _ultraGrabber.ProcessFileBegin += new EventHandler<ProcessFileEventArgs>(UltraGrabber_ProcessFile);
            _ultraGrabber.ProcessFileEnd += new EventHandler<ProcessFileEventArgs>(UltraGrabber_ProcessFileEnd);
            _ultraGrabber.ProcessFileError += new EventHandler<ProcessFileErrorEventArgs>(UltraGrabber_ProcessFileError);
            _ultraGrabber.ExecutingGrabber += new EventHandler<ExecutingGrabberEventArgs>(UltraGrabber_ExecutingGrabber);
            _ultraGrabber.GrabberError += new EventHandler<GrabberErrorEventArgs>(UltraGrabber_GrabberError);
            _ultraGrabber.LyricsFound += new EventHandler<LyricsFoundEventArgs>(UltraGrabber_LyricsFound);
        }

        static void UltraGrabber_ExecutingGrabber(object sender, ExecutingGrabberEventArgs e)
        {
            Console.WriteLine("Executing " + e.LyricGrabber.Name + " for " + e.Context.Filename + ".");
        }

        static void UltraGrabber_ProcessFileEnd(object sender, ProcessFileEventArgs e)
        {
            if (e.Context.Lyrics.Count == 0)
            {
                Console.WriteLine("!! Could not find lyrics for the file \"" + e.Context.Filename + "\" !!");
                _noLyricsFilenames.Add(e.Context.Filename);
            }
            else if (!_test)
            {
                Console.WriteLine("\nTagging lyrics to \"" + e.Context.Filename + "\" ...\n");
                e.Context.Tags.UnsyncedLyrics = e.Context.Lyrics[0].Lyrics;
                e.Context.Write();
                _taggedCount++;
            }
        }

        static void UltraGrabber_LyricsFound(object sender, LyricsFoundEventArgs e)
        {
            Console.WriteLine("The grabber " + e.LyricGrabber.Name + " has found lyrics for the file \"" + Path.GetFileName(e.Context.Filename) + "\".");

            if (_display)
            {
                Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                Console.WriteLine(e.Lyrics);
                Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
            }

            if (_saveLyricsToTextFile)
            {
                string textfilename = string.Format("{0}.{1}.txt", 
                                                    Path.GetFileNameWithoutExtension(e.Context.Filename), 
                                                    e.LyricGrabber.Name);

                textfilename = Path.Combine(Path.GetDirectoryName(e.Context.Filename), textfilename);

                Console.WriteLine("Saving lyrics to \"" + textfilename + "\" ...");

                if (_saveLyricsToTextFile)
                {
                    using (StreamWriter sw = File.CreateText(textfilename))
                    {
                        sw.Write(e.Lyrics);
                    }
                }
            }

            if (_test)
                e.Continue = true;
        }

        static void UltraGrabber_GrabberError(object sender, GrabberErrorEventArgs e)
        {
            if (e.Exception.GetType() == typeof(WebException))
            {
                Console.WriteLine("A web exception has occured. Disabling the grabber " + e.LyricGrabber.Name);
                e.LyricGrabber.Enabled = false;
            }
            else
            {
                Console.WriteLine("An error has occured while executing grabber " + e.LyricGrabber.Name);
            }

            e.Continue = true;
        }

        static void UltraGrabber_ProcessFileError(object sender, ProcessFileErrorEventArgs e)
        {
            Console.WriteLine("Error occured while processing file \"" + e.Filename + "\".");
            Console.WriteLine(e.Exception.ToString());
            e.Continue = true;
        }

        static void UltraGrabber_ProcessFile(object sender, ProcessFileEventArgs e)
        {
            Console.WriteLine("Processing file \"" + Path.GetFileName(e.Context.Filename) + "\"");

            if (!string.IsNullOrEmpty(e.Context.Tags.UnsyncedLyrics))
            {
                Console.WriteLine("File already contains lyrics.");

                if (_skip)
                    e.SkipFile = true;
                else
                {
                    if (!_force)
                    {
                        Console.Write("Overwrite? ");
                        ConsoleKeyInfo k = Console.ReadKey();
                        Console.Write("\n");

                        if (k.KeyChar != 'y')
                        {
                            e.SkipFile = true;
                        }
                    }
                }

                if (e.SkipFile)
                {
                    Console.WriteLine("Skipping.");
                    _skippedCount++;
                }
            }
        }

        static void UltraGrabber_ScanDirectory(object sender, ScanDirectoryEventArgs e)
        {
            Console.WriteLine("Scanning directory \"" + e.Directory + "\".");
        }

        private static bool ParseArguments(string[] args)
        {
            foreach (string arg in args)
            {
                if (arg[0] == '/')
                {
                    switch (arg[1])
                    {
                        case 'h':
                            DisplayUsage();
                            return false;

                        case 's':
                            _skip = true;
                            break;

                        case 'S':
                            _saveLyricsToTextFile = true;
                            break;

                        case 'f':
                            _force = true;
                            break;

                        case 'd':
                            _display = true;
                            break;

                        case 'r':
                            _ultraGrabber.Recursive = true;
                            break;

                        case 't':
                            _test = true;
                            break;

                        default:
                            Console.WriteLine("Unknown argument: " + arg);
                            return false;
                    }
                }
                else
                {
                    // Assume filename

                    _ultraGrabber.Filename = arg.Trim("\" \\/".ToCharArray());
                }
            }

            return true;
        }

        private static void DisplayUsage()
        {
            Assembly asm = Assembly.GetExecutingAssembly();

            string asmName = asm.GetName().Name;
            Console.WriteLine("Usage: {0} (filename|directory) [options]", asmName);
            Console.WriteLine("/help        Help!");
            Console.WriteLine("/skip        Skip files which already have lyrics.");
            Console.WriteLine("/force       No prompt for overwriting existing lyrics.");
            Console.WriteLine("/display     Display the found lyrics.");
            Console.WriteLine("/recursive   Updates all files beneath the given directory.");
            Console.WriteLine("/test        Turn on testing. Will not save the lyrics and will continue");
            Console.WriteLine("             executing grabber plugins even when lyrics has been found.");
            Console.WriteLine("/Save        Save the found lyrics in text files.");
        }
    }
}
